#include "qweeklytimer.h"

QWeeklyTimer::QWeeklyTimer(Qt::DayOfWeek dow, int h, int m)
{
	// Assign the time values to proper members
	this->assignTimeValues(dow, h, m);

    // Set the internal timer to check every minute
    _internaltimer = new QTimer(this);
    _internaltimer->setInterval(1000*60);
    _internaltimer->setSingleShot(false);
    connect(_internaltimer, SIGNAL(timeout()), this, SLOT(internalTimer_timedout()));
}

void QWeeklyTimer::start()
{
    this->initTimer();
    _internaltimer->start();
}

void QWeeklyTimer::stop()
{
    _internaltimer->stop();
}

void QWeeklyTimer::reschedule(Qt::DayOfWeek dow, int h, int m)
{
	// Assign the time values to proper members
	this->assignTimeValues(dow, h, m);

	// Initialize again according to the new schedule
	this->initTimer();
}

void QWeeklyTimer::assignTimeValues(Qt::DayOfWeek dow, int h, int m)
{
	// Assign the day of week value
	_dayofweek = dow;

	// Check and assign hours' value
	if ((h >=0) && (h <=23))
	{
		_hours = h;
	} else {
		throw "Invalid hours value passed to QWeeklyTimer.";
	}

	// Check and assign minutes' value
	if ((m >=0) && (m <=59))
	{
		_minutes = m;
	} else {
		throw "Invalid minutes value passed to QWeeklyTimer.";
	}

	// Seconds' value will always be zero
    _seconds = 0;
}

void QWeeklyTimer::initTimer()
{
    QDateTime* now = new QDateTime(QDateTime::currentDateTime());
    QDateTime* dt = new QDateTime(QDateTime::currentDateTime());
    dt->setTime(QTime(_hours, _minutes, _seconds));

    // If the day is today
    if (dayNumber(_dayofweek) == now->date().dayOfWeek()) {
        // if time 'dt' has passed then schedule for the next week
        if (*dt <= *now) *dt = dt->addDays(7);
    } else {
        // If the day has yet to come in this week
        if (dayNumber(_dayofweek) > now->date().dayOfWeek()) {
            int diff = dayNumber(_dayofweek) - now->date().dayOfWeek();
            *dt = dt->addDays(diff);
        } else {
            int diff = dayNumber(_dayofweek) - now->date().dayOfWeek();
            *dt = dt->addDays(diff);
            *dt = dt->addDays(7);
        }
    }

    // Set the next schedule
    uint ts = dt->toTime_t() - now->toTime_t();
    _nextschedule = new QDateTime(*now);
    _nextschedule->setTime_t(now->toTime_t() + ts);
}

int QWeeklyTimer::dayNumber(Qt::DayOfWeek dow)
{
    return (int) dow;
}

void QWeeklyTimer::internalTimer_timedout()
{
    if (isNowTheTime())
    {
        initTimer();
        emit timeout();
    }
    qDebug() << "QWeeklyTimer::internatTimer_Elapsed() was called.";
}

bool QWeeklyTimer::isNowTheTime()
{
    bool year=false, month=false, day=false, hour=false, minute=false;
    QDateTime* now = new QDateTime(QDateTime::currentDateTime());

    year = (now->date().year() == _nextschedule->date().year()) ? true:false;
    month = (now->date().month() == _nextschedule->date().month()) ? true:false;
    day = (now->date().day() == _nextschedule->date().day()) ? true:false;
    hour = (now->time().hour() == _nextschedule->time().hour()) ? true:false;
    minute = (now->time().minute() == _nextschedule->time().minute()) ? true:false;

    if (year && month && day && hour && minute)
        return true;
    else
        return false;
}

QDateTime* QWeeklyTimer::nextSchedule()
{
    return new QDateTime(*_nextschedule);
}

void QWeeklyTimer::setInterval(int msec)
{
    QTimer::setInterval(msec);
}
